<?php
/**
 * Represents a database connection, manages general database operations, and
 * stores properties describing the currently connected database.
 * 
 * @package Bedrock
 * @author Nick Williams
 * @version 1.0.0
 * @created 08/29/2008
 * @updated 08/29/2008
 */
class Bedrock_Model_Database extends Bedrock {
	const DB_TYPE_MYSQL = 0;
	const DB_TYPE_POSTGRES = 1;
	const DB_TYPE_MSSQL = 2;
	
	protected $_connection;
	protected $_name;
	protected $_type;
	protected $_tables;
	
	/**
	 * Initializes a database connection.
	 *
	 * @param array $databaseConfig the database configuration
	 */
	public function __construct($databaseConfig) {
		Bedrock_Common_Logger::logEntry();
		
		try {
			// Build Connection String
			$params = $databaseConfig->params;
			$dsn = $params->type . ':host=' . $params->host . ';dbname=' . $params->dbname;
			
			Bedrock_Common_Logger::info('Connecting to database "' . $params->dbname . '" on "' . $params->host . '"...');
			
			// Set Properties
			switch($params->type) {
				case 'mysql':
					$this->_type = self::DB_TYPE_MYSQL;
					break;
			}
			
			// Initialize Database Connection
			$this->_connection = new PDO($dsn, $params->username, $params->password);
			$this->_name = $params->dbname;
			$this->_dbConfig = $databaseConfig;
			
			parent::__construct();
			
			Bedrock_Common_Logger::logExit();
		}
		catch(PDOException $ex) {
			Bedrock_Common_Logger::exception($ex);
			Bedrock_Common_Logger::logExit();
			throw new Bedrock_Model_Exception('There was a problem retrieving the table information.');
		}
		catch(Exception $ex) {
			Bedrock_Common_Logger::exception($ex);
			Bedrock_Common_Logger::logExit();
			throw new Bedrock_Model_Exception('There was a problem connecting to the database.');
		}
	}
	
	/**
	 * Retrieves the requested table as a table object.
	 *
	 * @param string $tableName the name of the table to retrieve
	 * @return Bedrock_Model_Table the resulting table object
	 */
	public function __get($tableName) {
		Bedrock_Common_Logger::logEntry();
		
		try {
			// If requested table isn't cached, load it.
			if(!is_object($this->_tables[$tableName])) {
				$this->_tables[$tableName] = new Bedrock_Model_Table(array('name' => $tableName), $this);
				$this->_tables[$tableName]->load();
			}
			
			Bedrock_Common_Logger::logExit();
			return $this->_tables[$tableName];
		}
		catch(Exception $ex) {
			Bedrock_Common_Logger::exception($ex);
			Bedrock_Common_Logger::logExit();
			throw new Bedrock_Model_Exception('There was a problem retrieving the table information.');
		}
	}
	
	/**
	 * Loads all current database and table details into the database object.
	 */
	public function load() {
		Bedrock_Common_Logger::logEntry();
		
		try {
			// Get Table List
			$res = $this->_connection->query('SHOW TABLES');
			
			while($row = $res->fetch(PDO::FETCH_NUM)) {
				$this->__get($row[0]);
			}
			
			Bedrock_Common_Logger::logExit();
		}
		catch(Exception $ex) {
			Bedrock_Common_Logger::exception($ex);
			Bedrock_Common_Logger::logExit();
		}
	}
	
	/**
	 * Returns the current database connection.
	 *
	 * @return PDO the current database connection
	 */
	public function getConnection() {
		if($this->_connection) {
			return $this->_connection;
		}
		else {
			return NULL;
		}
	}
	
	/**
	 * Returns all tables currently stored with the Database object.
	 *
	 * @return array an array of the corresponding Table objects
	 */
	public function getTables() {
		return $this->_tables;
	}
	
	/**
	 * Returns configuration details for the current database connection.
	 *
	 * @return array an array containing the configuration details
	 */
	public function getConfig() {
		return $this->_dbConfig;
	}
	
	public function importTableSchemas($importSource, $importType) {
		// @todo implement method
	}
	
	public function exportTableSchemas($exportLocation, $exportType) {
		// @todo implement method
	}
	
	/**
	 * Imports all table data from the specified source directory.
	 *
	 * @param string $importSource the source directory containing the files to import
	 * @param integer $importType the type of data the source files use
	 * @param boolean $append whether or not to append the imported data to existing table data
	 */
	public function importTableData($importSource, $importType, $append = false) {
		Bedrock_Common_Logger::logEntry();
		
		try {
			// Setup
			$ext = '.' . Bedrock_Model_Table::typeToString($importType);
			$fileName = '';
			
			// Load Tables
			$this->load();
			
			// Import Data
			Bedrock_Common_Logger::info('Attempting to import table data for database "' . $this->_name . '" from location "' . $importSource . '" ...');
			
			foreach($this->_tables as $name => $table) {
				$fileName = $importSource . $name . $ext;
				
				if(is_file($fileName)) {
					Bedrock_Common_Logger::info('File "' . $fileName . '" found, importing for corresponding table...');
					$table->importData($fileName, $importType, $append);
				}
			}
			
			Bedrock_Common_Logger::logExit();
		}
		catch(Exception $ex) {
			Bedrock_Common_Logger::exception($ex);
			Bedrock_Common_Logger::logExit();
		}
	}
	
	/**
	 * Exports all table data from the database to the specified location.
	 *
	 * @param integer $exportType the data type to use
	 * @param string $exportLocation the location to which to export
	 */
	public function exportTableData($exportLocation, $exportType) {
		Bedrock_Common_Logger::logEntry();
		
		try {
			// Load Tables
			$this->load();
			
			Bedrock_Common_Logger::info('Exporting all table data for database "' . $this->_name . '" to location "' . $exportLocation . '" ...');
			
			// Export Data
			foreach($this->_tables as $name => $table) {
				Bedrock_Common_Logger::info('Exporting table "' . $name . '" ...');
				$table->exportData($exportLocation, $exportType);
			}
			
			Bedrock_Common_Logger::logExit();
		}
		catch(Exception $ex) {
			Bedrock_Common_Logger::exception($ex);
			Bedrock_Common_Logger::logExit();
		}
	}
}
?>